import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.UIManager;

public class Environment1 implements GlobalSettings {

	
	
    public static void main(String[] args) {
        new Environment1();
    }

    public Environment1() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }
               
                
                JFrame frame = new JFrame("Sampling based motion planning");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                                
                frame.add(new PaintPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class PaintPane extends JPanel {

        private List<Shape> grid;
        
        private List<Shape> startLoc;
        private List<Shape> goalLoc;
        List<Point> roots=new ArrayList<Point>();
       /* public ArrayList<ArrayList<Point>> trees;
        
        boolean fillMatrix[][];
        Point startPoint,goalPoint;*/

        JRadioButton start,obstacle,goal;   
        JButton solveButton;             

        public PaintPane() {
        	this.setLayout(null);
        	
        	
        	
        	JLabel startLabel,obstacleLabel,goalLabel;
            ButtonGroup buttonGroup=new ButtonGroup();
            
            start=new JRadioButton("start");
            start.setSize(20, 20);
            start.setLocation(550, 20);  
            startLabel=new JLabel("select START");
            startLabel.setLocation(570, -20);
            startLabel.setSize(100, 100);
            
            obstacle=new JRadioButton("obstacle");
            obstacle.setSize(20, 20);
            obstacle.setLocation(550, 50);
            obstacle.setSelected(true); 
            obstacleLabel=new JLabel("select Obstacle");
            obstacleLabel.setLocation(570,10);
            obstacleLabel.setSize(100, 100);
            
            goal=new JRadioButton("goal");
            goal.setSize(20, 20);
            goal.setLocation(550, 80);
            goalLabel=new JLabel("select Goal");
            goalLabel.setLocation(570,40);
            goalLabel.setSize(100, 100);
                        
            buttonGroup.add(goal);
            buttonGroup.add(start);
            buttonGroup.add(obstacle);
            obstacle.setSize(20, 20);
            
            solveButton=new JButton("Solve");
            solveButton.setSize(80, 20);
            solveButton.setLocation(550,100);
            //trees = new ArrayList<ArrayList<Point>>();	//list of lists
            solveButton.addActionListener(new ActionListener() {
            	@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					/*Algorithm starts here*/
            		//JOptionPane.showMessageDialog(solveButton,"solving!!");
            		GaussianSampling sample=new GaussianSampling();
            		roots=sample.getSampledPoints();
            		RRTAlgorithm rrt=new RRTAlgorithm();
            		trees.add(rrt.constructTree(startPoint));
            		for(Point root:roots)
            		{            			           			
            			trees.add(rrt.constructTree(root));
            		}
            		trees.add(rrt.constructTree(goalPoint));
            		//for(int i=0;i<startPoints.size();i++)
            			//System.out.println(startPoints.get(i)+"to"+endPoints.get(i));
            		System.out.println("Executing SRT algortihm:");
            		SRTAlgorithm srt=new SRTAlgorithm();
            		srt.generateRoadMap();
            		BuildPath path=new BuildPath();
            		path.findPath();
            		repaint();
				}
            });
            
            this.add(start);
            this.add(obstacle);
            this.add(goal);
            this.add(goalLabel);
            this.add(obstacleLabel);
            this.add(startLabel);
            this.add(solveButton);
                                 
            //fillMatrix=new boolean[gridCount][gridCount];
            grid = new ArrayList<>(5);
            /*fill = new ArrayList<>(5);*/
            startLoc = new ArrayList<>(5);
            goalLoc = new ArrayList<>(5);
           // startPoint=new Point();
           // goalPoint=new Point();
            
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                   if(obstacle.isSelected()){
                	for (Shape shape : grid) {
                        if (shape.contains(e.getPoint())) {
                            if (fill.contains(shape)) {
                                fill.remove(shape);
                                //System.out.println(e.getPoint());
                               fillMatrix[e.getPoint().y/(windowSizeY/gridCount)][e.getPoint().x/(windowSizeX/gridCount)]=false;
                            } else {
                                fill.add(shape);
                               // System.out.println(e.getPoint());
                               fillMatrix[e.getPoint().y/(windowSizeY/gridCount)][e.getPoint().x/(windowSizeX/gridCount)]=true;
                            }
                        }
                    }
                   }
                   else
                	   if(start.isSelected()){
                       	  for (Shape shape : grid)
                               if (shape.contains(e.getPoint())) {
                            	       startLoc.clear();
                                	   startLoc.add(shape);
                                	   startPoint.x=e.getPoint().y/(windowSizeY/gridCount);
                                	   startPoint.y=e.getPoint().x/(windowSizeX/gridCount);
                               }
                       }
                   else
                   {
                	   
                    	   if(goal.isSelected()){
                           	for (Shape shape : grid)
                                   if (shape.contains(e.getPoint())) {
                                	      goalLoc.clear();
                                	      goalLoc.add(shape);
                                	      goalPoint.x=e.getPoint().y/(windowSizeY/gridCount);
                                   	   	  goalPoint.y=e.getPoint().x/(windowSizeX/gridCount);
                                   }
                               }
                   }
                   repaint();
                }
            });

            int colWidth = windowSizeX /gridCount;
            int rowHeight = windowSizeY /gridCount;

            for (int row = 0; row <gridCount; row++) {
                for (int col = 0; col <gridCount; col++) {
                    grid.add(new Rectangle(colWidth * col, rowHeight * row, colWidth, rowHeight));
                }
            }

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(windowSizeX+250, windowSizeY+10);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.BLACK);
            for (Shape cell : fill) {
                g2d.fill(cell);
            }
            g2d.setColor(Color.GREEN);
            for (Shape cell : startLoc) {
                g2d.fill(cell);
            }
            g2d.setColor(Color.RED);
            for (Shape cell : goalLoc) {
                g2d.fill(cell);
            }
            
            g2d.setColor(Color.MAGENTA);
            
            for(ArrayList<Point> list:trees)
            	for(Point p:list)
            		if(!((p.equals(startPoint))||p.equals(goalPoint)))
            			g2d.fill(getShape(new Point(p.y*(windowSizeY/gridCount),p.x*(windowSizeX/gridCount))));
            
           // g2d.setColor(Color.BLACK);
                       		
            
            g2d.setColor(Color.BLUE);
            for(Point p:roots)
            	g2d.fill(getShape(new Point(p.y*(windowSizeY/gridCount),p.x*(windowSizeX/gridCount))));
                        
            g2d.setColor(Color.BLACK);
            for (Shape cell : grid) {
                g2d.draw(cell);
            }
            
           /* g2d.setColor(Color.BLUE);
            for(int j=0;j<trees.size();j++)
    		{
    			Point x=trees.get(j).get(0);
    			for(ArrayList<Point> l:Nt.get(j))
    			{
    				Point y=l.get(0);
    				g2d.drawLine(x.y*(windowSizeY/gridCount)+5, x.x*(windowSizeX/gridCount)+5, y.y*(windowSizeY/gridCount)+5, y.x*(windowSizeX/gridCount)+5);
    			}
    		}*/
            
            g2d.setColor(Color.MAGENTA);
            for(int i=0;i<startConnectTreePoints.size();i++)
            {
            			//System.out.println(startConnectTreePoints.get(i)+" to "+ endConnectTreePoints.get(i));
            	       	g2d.drawLine(startConnectTreePoints.get(i).y*(windowSizeY/gridCount)+5, startConnectTreePoints.get(i).x*(windowSizeX/gridCount)+5, endConnectTreePoints.get(i).y*(windowSizeY/gridCount)+5, endConnectTreePoints.get(i).x*(windowSizeX/gridCount)+5);            
            }
            
            g2d.setColor(Color.BLACK);
            for(int i=0;i<startPathPoints.size();i++)
            	{
            	       	g2d.drawLine(startPathPoints.get(i).y*(windowSizeY/gridCount)+5, startPathPoints.get(i).x*(windowSizeX/gridCount)+5, endPathPoints.get(i).y*(windowSizeY/gridCount)+5, endPathPoints.get(i).x*(windowSizeX/gridCount)+5);            
            	}
            
            g2d.setColor(Color.RED);
            for(int i=0;i<startPoints.size();i++)
            	{
            	       	g2d.drawLine(startPoints.get(i).y*(windowSizeY/gridCount)+5, startPoints.get(i).x*(windowSizeX/gridCount)+5, endPoints.get(i).y*(windowSizeY/gridCount)+5, endPoints.get(i).x*(windowSizeX/gridCount)+5);            
            	}
            }
        private Shape getShape(Point qnew) {
    		// TODO Auto-generated method stub
    		for (Shape shape : grid) {
                if (shape.contains(qnew)) {
                	return shape;
                }
    		}
    		return null;
    	}

    }

	
}